/*-------------------------------------------------------------------------
 *
 * rewriteRemove.c
 *	  删除重写规则的例程
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *	  src/backend/rewrite/rewriteRemove.c
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include "access/genam.h"
#include "access/htup_details.h"
#include "access/sysattr.h"
#include "access/table.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_rewrite.h"
#include "miscadmin.h"
#include "rewrite/rewriteRemove.h"
#include "utils/acl.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"

/*
 * 规则删除的核心。
 */
void RemoveRewriteRuleById(Oid fc_ruleOid)
{
	Relation	fc_RewriteRelation;
	ScanKeyData fc_skey[1];
	SysScanDesc fc_rcscan;
	Relation	fc_event_relation;
	HeapTuple	fc_tuple;
	Oid			fc_eventRelationOid;

	/*
	 * 打开 pg_rewrite 关系。
	 */
	fc_RewriteRelation = table_open(RewriteRelationId, RowExclusiveLock);

	/*
	 * 找到目标规则的元组。
	 */
	ScanKeyInit(&fc_skey[0],
				Anum_pg_rewrite_oid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(fc_ruleOid));

	fc_rcscan = systable_beginscan(fc_RewriteRelation, RewriteOidIndexId, true,
								NULL, 1, fc_skey);

	fc_tuple = systable_getnext(fc_rcscan);

	if (!HeapTupleIsValid(fc_tuple))
		elog(ERROR, "could not find tuple for rule %u", fc_ruleOid);

	/*
	 * 我们最好抓取 AccessExclusiveLock 以确保没有查询可能依赖于此规则。
	 * （注意：如果不是 ON SELECT 规则，较弱的锁就足够了。）
	 */
	fc_eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(fc_tuple))->ev_class;
	fc_event_relation = table_open(fc_eventRelationOid, AccessExclusiveLock);

	if (!allowSystemTableMods && IsSystemRelation(fc_event_relation))
		ereport(ERROR,
				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
				 errmsg("permission denied: \"%s\" is a system catalog",
						RelationGetRelationName(fc_event_relation))));

	/*
	 * 现在删除该规则的 pg_rewrite 元组。
	 */
	CatalogTupleDelete(fc_RewriteRelation, &fc_tuple->t_self);

	systable_endscan(fc_rcscan);

	table_close(fc_RewriteRelation, RowExclusiveLock);

	/*
	 * 发布共享无效通知，强制所有后端（包括我！）更新与新规则集的 relcache 条目。
	 */
	CacheInvalidateRelcache(fc_event_relation);

	/* 关闭关系，但在提交之前保持锁... */
	table_close(fc_event_relation, NoLock);
}
